/**
 * desc: ES2015 新特性 Arrow Function 箭头函数
 * User : hjt
 * Date : 2017/1/5
 */

    //http://www.jb51.net/article/50770.htm

    /*
    * 箭头函数是ECMAScript 6引入了一种用「箭头」（=>）来定义函数的新语法
    * 箭头函数与传统的JavaScript函数主要区别:
    * 1.对 this 的关联。函数内置 this 的值，取决于箭头函数在哪儿定义，而非箭头函数执行的上下文环境。
     2.new 不可用。箭头函数不能使用 new 关键字来实例化对象，不然会报错。
     3.this 不可变。函数内置 this 不可变，在函数体内整个执行环境中为常量。
     4.没有arguments对象。更不能通过arguments对象访问传入参数。只能使用显式命名或其他ES6新特性来完成。
    *
    * */


//一、语法
//箭头函数的语法很简单，定义自变量，然后是箭头和函数主体。自变量和主题因使用不同可以采用更简洁的格式。


//传一个参数和返回一个值的箭头函数
//传一个参数就直接写就好了，不用加小括号
//箭头指向函数主体，不过函数主体也只是简单的一条返回语句，所以也不用加大括号。函数构造完毕赋给reflect加以引用
var reflect = value => value;
// 等同于：

var reflect = function(value) {
    return value;
};



//传入多个参数，则应加上小括号
var sum = (num1, num2) => num1 + num2;
// 等同于：
var sum = function(num1, num2) {
    return num1 + num2;
};


//不需要传入参数，那也要以空括号来代替。
var sum = () => 1 + 2;
// 等同于：
var sum = function() {
    return 1 + 2;
};

//若你想使用标准的函数体，或者函数体内可能有更多的语句要执行，则要用大括号将函数体括起来，并明确定义返回值。
var sum = (num1, num2) => { return num1 + num2; }
//等同于：
var sum = function(num1, num2) {
    return num1 + num2;
};


//大括号是函数主体的标志


//箭头函数若要返回自定义对象的话，就必须用小括号把该对象括起来先
//用小括号包含大括号则是对象的定义，而非函数主体
var getTempItem = id => ({
    id: id,
    name: "Temp"
});
// 等同于：
var getTempItem = function(id) {
    return {
        id: id,
        name: "Temp"
    };
};


//二、使用

//JavaScript最常见错误之一就是函数内部this关联。因为this是根据函数当前的执行环境去取值的，这样就会在调用时产生误解，以导致对其他的不相关对象产生了影响
var PageHandler = {
    id: "123456",
    init: function() {
        document.addEventListener("click", function(event) {
            this.doSomething(event.type); // error
        }, false);
    },
    doSomething: function(type) {
        console.log("Handling " + type + " for " + this.id);
    }
};

//在这段代码中，本意是想让PageHandler的init()方法用于构建交互作用，并在点击事件处理函数中调用this.doSomething()。
//但是代码并未按设计初衷来执行，运行时this指向了全局对象而不是PageHandler，从而造成this.doSomething()调用无效出现报错，
// 因为全局对象中不存在doSomething方法

//当然，可以在函数中使用bind()将this与PageHandler明确关联起来
var PageHandler = {

    id: "123456",

    init: function() {
        document.addEventListener("click", (function(event) {
            this.doSomething(event.type);
        }).bind(this), false);
    },

    doSomething: function(type) {
        console.log("Handling " + type + " for " + this.id);
    }
};

/*
* 虽然看着有些怪，但现在代码执行是符合预期的。通过调用函数的bind(this)，
* 又创建了一个已关联现有this的新函数返回，就是说为了达到目的额外又包了一层。
 因为箭头函数已经支持this关联，所以这里用箭头函数会更爽快些，看下例：
* */
var PageHandler = {

    id: "123456",

    init: function() {
        document.addEventListener("click",
            event => this.doSomething(event.type), false);
    },

    doSomething: function(type) {
        console.log("Handling " + type + " for " + this.id);
    }
};
//这个实例中的事件处理函数调用了this.doSomething()的箭头函数。this的取值即为init()内的this值。故而它等效于bind()。



//定制比较器来排列数组
var result = values.sort(function(a, b) {
    return a - b;
});
//若使用箭头函数，则可写成很精炼的代码
var result = values.sort((a, b) => a - b);


//三、补充
/*
* 箭头函数的确与传统函数有不同之处，但仍存在共同的特点。例如：
 1.对箭头函数进行typeof操作会返回“function”。
 2.箭头函数仍是Function的实例，故而instanceof的执行方式与传统函数一致。
 3.call/apply/bind方法仍适用于箭头函数，但就算调用这些方法扩充当前作用域，this也依旧不会变化。
 箭头函数与传统函数最大的不同之处在，禁用new操作。
* */






